home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-11-01 | 12.7 KB | 669 lines | [TEXT/CWIE] |
-
- /* ----------------------- 0xED Command Dispatcher ------------------------------
- not implemented: INI, INIR, IND, INDR, OUTI, OTIR, OUTD, OTDR
- illegals marked with *) are taken from G.Lunter's Z80 v3.0 documentation
-
- Z80 Emulator
- Copyright (C) 1994 G.Woigk
-
- This file is part of Mac Spectacle and it is free software
- See application.c for details
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- */
-
-
- cmd_ED:
-
- // ----- read next byte of instruction ----------------------------
- move.b (ip)+,db
-
-
- // ----- increment r register -----------------------------------
- #if EXACT_R
- addq.b #1,r
- #endif
-
-
- // ----- debugger related testings -------------------------------
- #if CMD_PROFILE || cmd_firstuse
- movea.l cnt_ed,a0
- // addq.l #1,(a0,db.l*4)
- lsl #2,db
- addq.l #1,(a0,db.l)
- lsr #2,db
- #if cmd_firstuse
- bne.s cmded2
- }; Do_1st_Instr ( ip-2 ); asm {
- cmded2:
- #endif
- #endif
-
-
- // ----- Execute instruction -------------------------------------
- dc.w 0x41FB, 0x4A06 // lea *+$08(D4.l*2),A0
- adda.w (a0),a0
- jmp (a0)
-
- ed_tab: dc.w EDNOP, EDNOP, EDNOP, EDNOP, EDNOP, EDNOP, EDNOP, EDNOP
- dc.w EDNOP, EDNOP, EDNOP, EDNOP, EDNOP, EDNOP, EDNOP, EDNOP
- dc.w EDNOP, EDNOP, EDNOP, EDNOP, EDNOP, EDNOP, EDNOP, EDNOP
- dc.w EDNOP, EDNOP, EDNOP, EDNOP, EDNOP, EDNOP, EDNOP, EDNOP
- dc.w EDNOP, EDNOP, EDNOP, EDNOP, EDNOP, EDNOP, EDNOP, EDNOP
- dc.w EDNOP, EDNOP, EDNOP, EDNOP, EDNOP, EDNOP, EDNOP, EDNOP
- dc.w EDNOP, EDNOP, EDNOP, EDNOP, EDNOP, EDNOP, EDNOP, EDNOP
- dc.w EDNOP, EDNOP, EDNOP, EDNOP, EDNOP, EDNOP, EDNOP, EDNOP
-
- dc.w ed_40, ed_41, ed_42, ed_43, ed_44, ed_45, ed_46, ed_47
- dc.w ed_48, ed_49, ed_4a, ed_4b, ed_4c, ed_4d, ed_4e, ed_4f
- dc.w ed_50, ed_51, ed_52, ed_53, ed_54, ed_55, ed_56, ed_57
- dc.w ed_58, ed_59, ed_5a, ed_5b, ed_5c, ed_5d, ed_5e, ed_5f
- dc.w ed_60, ed_61, ed_62, ed_63, ed_64, ed_65, ed_66, ed_67
- dc.w ed_68, ed_69, ed_6a, ed_6b, ed_6c, ed_6d, ed_6e, ed_6f
- dc.w ed_70, ed_71, ed_72, ed_73, ed_74, ed_75, ed_76, ed_77
- dc.w ed_78, ed_79, ed_7a, ed_7b, ed_7c, ed_7d, ed_7e, ed_7f
-
- dc.w EDNOP, EDNOP, EDNOP, EDNOP, EDNOP, EDNOP, EDNOP, EDNOP
- dc.w EDNOP, EDNOP, EDNOP, EDNOP, EDNOP, EDNOP, EDNOP, EDNOP
- dc.w EDNOP, EDNOP, EDNOP, EDNOP, EDNOP, EDNOP, EDNOP, EDNOP
- dc.w EDNOP, EDNOP, EDNOP, EDNOP, EDNOP, EDNOP, EDNOP, EDNOP
- dc.w ed_a0, ed_a1, ed_a2, ed_a3, EDNOP, EDNOP, EDNOP, EDNOP
- dc.w ed_a8, ed_a9, ed_aa, ed_ab, EDNOP, EDNOP, EDNOP, EDNOP
- dc.w ldir, ed_b1, ed_b2, ed_b3, EDNOP, EDNOP, EDNOP, EDNOP
- dc.w lddr, ed_b9, ed_ba, ed_bb, EDNOP, EDNOP, EDNOP, EDNOP
-
- dc.w EDNOP, EDNOP, EDNOP, EDNOP, EDNOP, EDNOP, EDNOP, EDNOP
- dc.w EDNOP, EDNOP, EDNOP, EDNOP, EDNOP, EDNOP, EDNOP, EDNOP
- dc.w EDNOP, EDNOP, EDNOP, EDNOP, EDNOP, EDNOP, EDNOP, EDNOP
- dc.w EDNOP, EDNOP, EDNOP, EDNOP, EDNOP, EDNOP, EDNOP, EDNOP
- dc.w EDNOP, EDNOP, EDNOP, EDNOP, EDNOP, EDNOP, EDNOP, EDNOP
- dc.w EDNOP, EDNOP, EDNOP, EDNOP, EDNOP, EDNOP, EDNOP, EDNOP
- dc.w EDNOP, EDNOP, EDNOP, EDNOP, EDNOP, EDNOP, EDNOP, EDNOP
- dc.w EDNOP, EDNOP, EDNOP, EDNOP, EDNOP, EDNOP, EDNOP, EDNOP
-
-
- // handle not implemented block commands
- ed_a2: // ini
- ed_a3: // outi
- ed_aa: // ind
- ed_ab: // outd
- ed_b2: // inir
- ed_b3: // otir
- ed_ba: // indr
- ed_bb: // otdr
- bra exit_illinstr2
-
- // handle 0xED00 ... 0xED3F
- // handle 0xED80 ... 0xEDBF (except legal instructions (block move/compare/io))
- // handle 0xEDC0 ... 0xEDFF
- EDNOP: more4 // 8 T cycles: 4+4
- do_info_illegals2
- m_next
-
- // ####################################################################
-
- ed_77: // nop *)
- ed_7f: // nop *)
- more4 // 8 T cycles
- do_info_illegals2
- m_next
-
-
- ed_4c: // neg *)
- ed_54: // neg *)
- ed_5c: // neg *)
- ed_64: // neg *)
- ed_6c: // neg *)
- ed_74: // neg *)
- ed_7c: // neg *)
- do_info_illegals2
- ed_44: more4 // neg
- neg.b a
- move ccr,f
- m_next
-
-
- ed_55: // retn G.Lunter: ret, retn, or reti
- ed_65: // retn G.Lunter: ret, retn, or reti
- ed_75: // retn G.Lunter: ret, retn, or reti
- do_info_illegals2
- ed_45: more8 // retn
- more2 // 14 T cycles: 4+2+8
- do_info_retn
- move.w (rp)+,core
- rol.w #8,core
- movea.l core,ip
- move.b IFF2,IFF1
- m_next
-
-
- ed_5d: // reti G.Lunter: ret, reti, or retn
- ed_6d: // reti G.Lunter: ret, reti, or retn
- ed_7d: // reti G.Lunter: ret, reti, or retn
- do_info_illegals2
- ed_4d: more8 // reti
- more2 // 14 T cycles: 4+8+2
- do_info_reti
- ed4d1: move.w (rp)+,core
- rol.w #8,core
- movea.l core,ip
- m_next
-
-
- ed_4e: // im 0 *)
- ed_66: // im 0 *)
- ed_6e: do_info_illegals2 // im 0 *)
- ed_46: more4 // im 0
- do_info_im
- move.b #0,IM
- m_next
-
- ed_76: do_info_illegals2 // im 1 *)
- ed_56: more4 // im 1
- do_info_im
- move.b #1,IM
- m_next
-
- ed_7e: do_info_illegals2 // im 2 *)
- ed_5e: more4 // im 2
- do_info_im
- move.b #2,IM
- m_next
-
-
- ed_47: more5 // ld i,a
- do_info_i
- move.b a,RI
- m_next
-
- ed_4f: more5 // ld r,a
- do_info_r
- ld_r_a
- m_next
-
- ed_57: more5 // ld a,i
- do_info_i
- and.b #1,f
- move.b RI,a
- move ccr,d0
- or.b d0,f
- tst.b IFF2
- beq nxtirpt
- bset #1,f // copy iff2 to P/V
- m_next
-
- ed_5f: more5 // ld a,r
- do_info_r
- ld_a_r // returns with flags Z and S set
- move ccr,d0
- and.b #1,f // preserve C flag
- or.b d0,f
- tst.b IFF2
- beq nxtirpt
- bset #1,f // copy iff2 to P/V
- m_next
-
-
- // ----- Input commands ---------------------------------------
- #define do_input_bc(DEST) \
- more8 ;\
- sto_cc ;\
- move.w BC,-(a7) ;\
- jsr Do_Input ;\
- addq.l #2,a7 ;\
- move.b d0,DEST ;\
- move.b d0,db ;\
- and.b #1,f ;\
- or.b (logflags,db.l),f ;\
- load_rom_end ;\
- m_next
-
- ed_40: do_input_bc(RB)
- ed_48: do_input_bc(RC)
- ed_50: do_input_bc(RD)
- ed_58: do_input_bc(RE)
- ed_60: do_input_bc(RH)
- ed_68: do_input_bc(RL)
- ed_70: do_input_bc(db)
- ed_78: do_input_bc(a)
-
-
- // ----- Output commands ------------------------------------------------
- #define do_output_bc(DATA) \
- more8 ;\
- sto_cc ;\
- move.b DATA,-(a7) ;\
- move.w BC,-(a7) ;\
- jsr Do_Output ;\
- addq.l #4,a7 ;\
- load_rom_end ;\
- m_next
-
- ed_41: do_output_bc(RB)
- ed_49: do_output_bc(RC)
- ed_51: do_output_bc(RD)
- ed_59: do_output_bc(RE)
- ed_61: do_output_bc(RH)
- ed_69: do_output_bc(RL)
- ed_71: do_info_illegals2 // out (c),0
- do_output_bc(#0)
- ed_79: do_output_bc(a)
-
-
- // ----- sbc hl,ss ------------------------------------------------
-
- ed_42: more8 // sbc hl,bc
- more3 // 15 T states: 4+8+3
- move.w BC,d0
- move.w HL,d1
- lsr.b #1,f
- cmp d0,d0 // set Z flag
- subx.w d0,d1
- move ccr,f
- move.w d1,HL
- m_next
-
- ed_52: more8 // sbc hl,de
- more3
- move.w DE,d0
- move.w HL,d1
- lsr.b #1,f
- cmp d0,d0 // Z-Flag setzen!
- subx.w d0,d1
- move ccr,f
- move.w d1,HL
- m_next
-
- ed_62: more8 // sbc hl,hl
- more3
- lsr.b #1,f
- cmp d0,d0 // Z-Flag setzen!
- subx.w d0,d0
- move ccr,f
- move.w d0,HL
- m_next
-
- ed_72: more8 // sbc hl,sp
- more3
- move.w rp,d0
- move.w HL,d1
- lsr.b #1,f
- cmp d0,d0 // Z-Flag setzen!
- subx.w d0,d1
- move ccr,f
- move.w d1,HL
- m_next
-
-
- // ----- ld (nn),ss --------------------------------------------------
-
- #if rom_protection
- sto_bc: move.w BC,d0
- bra store_word
- sto_de: move.w DE,d0
- bra store_word
- #endif
-
- ed_43: more8 // ld (nn),bc
- more8
- move.w (ip)+,core
- rol.w #8,core
- movea.l core,a0
- if_rom(sto_bc)
- move.b RC,(a0)+
- move.b RB,(a0)
- m_next
-
- ed_53: more8 // ld (nn),de
- more8
- move.w (ip)+,core
- rol.w #8,core
- movea.l core,a0
- if_rom(sto_de)
- move.b RE,(a0)+
- move.b RD,(a0)
- m_next
-
- ed_73: more8 // ld (nn),sp
- more8
- move.w (ip)+,core
- rol.w #8,core
- movea.l core,a0
- move.w rp,d0
- if_rom(store_word)
- rol.w #8,d0
- move.w d0,(a0)
- m_next
-
-
- // ----- ld ss,(nn) --------------------------------------------------------
-
- ed_4b: more8 // ld bc,(nn)
- more8 // 20 T cycles: 4+8+8
- move.w (ip)+,core
- rol.w #8,core
- movea.l core,a0
- move.b (a0)+,RC
- move.b (a0),RB
- m_next
-
- ed_5b: more8 // ld de,(nn)
- more8
- move.w (ip)+,core
- rol.w #8,core
- movea.l core,a0
- move.b (a0)+,RE
- move.b (a0),RD
- m_next
-
- ed_6b: more8 // ld hl,(nn)
- more8
- move.w (ip)+,core
- rol.w #8,core
- movea.l core,a0
- move.b (a0)+,RL
- move.b (a0),RH
- m_next
-
- ed_7b: more8 // ld sp,(nn)
- more8
- move.w (ip)+,core
- rol.w #8,core
- movea.l core,a0
- move.w (a0),core
- rol.w #8,core
- movea.l core,rp
- bne nxtirpt
- adda.l #0x00010000,rp // falls sp := ramend
- m_next
-
-
- // ----- adc hl,ss ---------------------------------------------
-
- ed_4a: more8 // adc hl,bc
- more3 // 15 T cycles: 4+8+3
- move.w BC,d0
- move.w HL,d1
- lsr.b #1,f
- cmp d0,d0 // Z-Flag setzen!
- addx.w d0,d1
- move ccr,f
- move.w d1,HL
- m_next
-
- ed_5a: more8 // adc hl,de
- more3
- move.w DE,d0
- move.w HL,d1
- lsr.b #1,f
- cmp d0,d0 // Z-Flag setzen!
- addx.w d0,d1
- move ccr,f
- move.w d1,HL
- m_next
-
- ed_6a: more8 // adc hl,hl
- more3
- move.w HL,d0
- lsr.b #1,f
- cmp d0,d0 // Z-Flag setzen!
- addx.w d0,d0
- move ccr,f
- move.w d0,HL
- m_next
-
- ed_7a: more8 // adc hl,sp
- more3
- move.w rp,d0
- move.w HL,d1
- lsr.b #1,f
- cmp d0,d0 // Z-Flag setzen!
- addx.w d0,d1
- move ccr,f
- move.w d1,HL
- m_next
-
-
- // ----- BCD arithmetics ----------------------------------------------
-
- ed_67: more8 // rrd new: 10.4.95
- more6
- movea.l AHL,a0
-
- move.b (a0),db // db = old (hl)
- lsr.b #4,db
- lsl.w #4,a
- or.b a,db // db = new (hl)
-
- move.b (a0),a
- lsl.b #4,a
- lsr.w #4,a
-
- and.b #1,f
- or.b (logflags,a.w),f
- store_db
-
-
- ed_6f: more8 // rld new: 10.4.95
- more6
- movea.l AHL,a0
-
- move.b (a0),db // db = old (hl)
- lsl.b #4,db
- moveq #0x0F,d0
- and.b a,d0
- or.b d0,db // db = new (hl)
-
- sub.b d0,a
- move.b (a0),d0
- lsr.b #4,d0
- or.b d0,a
-
- and.b #1,f
- or.b (logflags,a.w),f
- store_db
-
-
- // ----- block instructions ---------------------------------------------
-
- ed_a9: movea.l AHL,a0 // cpd
- subq.w #1,HL
- bra.s cpi1
-
- ed_a1: movea.l AHL,a0 // cpi modified 11.apr.95 KIO !
- addq.w #1,HL
- cpi1: more8
- more4
- and.b #0x01,f
- subq.w #1,BC
- beq.s cpi2
- addq.b #2,f // P/V = 1 if BC<>0
- cpi2: cmp.b (a0),a
- move ccr,d0
- and.b #0x0c,d0
- or.b d0,f
- m_next
-
-
- ed_b9: moveq #-1,d1 // cpdr
- bra.s cpir0
-
- ed_b1: moveq #1,d1 // cpir modified 11.apr.95 KIO !
- cpir0: and.b #1,f // preserve c flag
- move.w HL,core
- move.w BC,d0
- #if EXACT_R
- add.b d0,r
- add.b d0,r
- subq.b #2,r
- #endif
- #if exact_timing
- more8
- more4 // 'last' byte takes 16 T cycles
- subq.w #1,d0
- mulu #21,d0
- sub.l d0,cc
- move.w BC,d0 // load again
- #endif
- cpir1: move.l core,a0
- add.w d1,core // hl+1 or hl-1, depending on cpir or cpdr
- subq.w #1,d0 // bc-1
- beq.s cpir2 // end of buffer
- cmp.b (a0),a
- bne.s cpir1
- addq.b #2,f // p=1
- #if EXACT_R
- sub.b d0,r // RC
- sub.b d0,r // RC
- #endif
- #if exact_timing
- moveq #21,d1
- mulu d0,d1 // bc (rest)
- add.l d1,cc
- #endif
- cpir2: move.w core,HL
- move.w d0,BC
- cmp.b (a0),a
- move ccr,d0
- and.b #0x0C,d0 // z and s flag
- or.b d0,f
- bra nxtirpt
-
-
- #if rom_protection
- lddx: move.b (a1),db
- bra store_byte
- #endif
-
- ed_a8: moveq #-1,d0 // ldd (hl) -> (de) modified 11.apr.95 KIO !
- bra.s ldd1
-
- ed_a0: moveq #1,d0 // ldi (hl) -> (de)
- ldd1: more8
- more4
- bset #1,f // P/V = 1 if BC<>0
- subq.w #1,BC
- bne.s ldd2
- subq.b #2,f // P/V = 0 if BC==0
- ldd2: movea.l AHL,a1
- movea.l ADE,a0
- add.w d0,HL
- add.w d0,DE
- if_rom(lddx)
- move.b (a1),(a0)
- m_next
-
-
- // ===== BLOCK MOVE =======================================
-
- ldir: bclr #1,f // P/V=0
- #if EXACT_R
- add.b BC,r
- add.b BC,r
- subq.b #2,r
- #endif
- #if exact_timing
- more8
- more4 // 'last' byte takes 16 T cycles
- move.w BC,d0
- subq.w #1,d0
- mulu #21,d0
- sub.l d0,cc
- #endif
- movea.l AHL,a1
- movea.l ADE,a0
- move.w BC,d0
- beq.s sldir // slow ldir: complete core shifts (don't worry, be happy!)
- clr.w BC
- add.w d0,HL
- bcs.s sldir1 // slow ldir: source pointer wraps
- add.w d0,DE
- bcs.s sldir2 // slow ldir: destination pointer wraps
- if_rom(sldir2) // slow ldir: first target byte is in rom
- // quick ldir: move d0.w bytes (a1)+ -> (a0)+
- subq.w #1,d0
- ldir1: move.b (a1)+,(a0)+
- dbf d0,ldir1
- bra nxtirpt
-
-
- #if rom_protection
- ldirx: movem.l d0-d2,-(a7)
- move.b (a1),-(a7)
- move.w a0,-(a7)
- jsr write_to_rom
- addq.l #4,a7
- movem.l (a7)+,d0-d2
- bra.s sldir5
- #endif
-
-
- sldir: add.w d0,HL
- sldir1: add.w d0,DE
- sldir2: moveq #1,db
- bra.s sldir3
-
- slddr: sub.w d0,HL
- slddr1: sub.w d0,DE
- slddr2: moveq #-1,db
-
- sldir3: move.w d0,core // counter
- subq.w #1,core
- move.l a0,d0
- move.l a1,d1
-
- sldir4: movea.l d0,a0
- movea.l d1,a1
- if_rom(ldirx)
- move.b (a1),(a0)
- sldir5: add.w db,d0
- add.w db,d1
- dbf core,sldir4
-
- moveq #0,db
- bra nxtirpt
-
-
-
-
- lddr: bclr #1,f // P/V=0
- #if EXACT_R
- add.b BC,r
- add.b BC,r
- subq.b #2,r
- #endif
- #if exact_timing
- more8
- more4 // 'last' byte takes 16 T cycles
- move.w BC,d0
- subq.w #1,d0
- mulu #21,d0
- sub.l d0,cc
- #endif
- movea.l AHL,a1
- movea.l ADE,a0
- move.w BC,d0
- beq.s slddr // slow ldir: complete core shifts (don't worry, be happy!)
- clr.w BC
- sub.w d0,HL
- bcs.s slddr1 // slow ldir: source pointer wraps
- sub.w d0,DE
- bcs.s slddr2 // slow ldir: destination pointer wraps
- #if rom_protection
- cmp.w DE,rom_end
- bhi.s slddr2
- #endif
- // quick lddr: move d0.w bytes (a1)- -> (a0)-
- addq.l #1,a0
- addq.l #1,a1
- subq.w #1,d0
- lddr1: move.b -(a1),-(a0)
- dbf d0,lddr1
- bra nxtirpt
-
-
-
-
-